package org.termine.filter;

import java.io.IOException;
import java.util.Collections;
import java.util.LinkedList;

import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.termine.jsf.LoginJSF;

public class SecurityFilter implements Filter {

	private static final Logger logger = LoggerFactory.getLogger(SecurityFilter.class);

	private final static LinkedList<String> ALLOWED_REQUESTS_ANONYM = new LinkedList<String>();
	private final static LinkedList<String> ALLOWED_REQUESTS_CLIENT = new LinkedList<String>();
	private final static LinkedList<String> ALLOWED_REQUESTS_PROVIDER = new LinkedList<String>();

	static {
		Collections.addAll(ALLOWED_REQUESTS_ANONYM, "/faces/anonym/*", "/", "/javax.faces.resource/*");
		Collections.addAll(ALLOWED_REQUESTS_CLIENT, "/faces/client/*", "/faces/common/*", "/", "/javax.faces.resource/*");
		Collections.addAll(ALLOWED_REQUESTS_PROVIDER, "/faces/provider/*", "/faces/common/*", "/", "/javax.faces.resource/*");
	}

	@Override
	public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException,
			ServletException {

		HttpServletRequest httpRequest = (HttpServletRequest) request;
		HttpSession session = httpRequest.getSession();
		LoginJSF loginJsf = (LoginJSF) session.getAttribute("loginJSF");
		String requestPath = httpRequest.getRequestURI().replace(httpRequest.getContextPath(), "");
		String role = loginJsf != null ? loginJsf.getWhoAmI() : "ANONYM";

		boolean requestAllowed = false;
		LinkedList<String> allowedRequestsForRole = "CLIENT".equalsIgnoreCase(role) ? ALLOWED_REQUESTS_CLIENT : ("PROVIDER"
				.equalsIgnoreCase(role) ? ALLOWED_REQUESTS_PROVIDER : ALLOWED_REQUESTS_ANONYM);

		for (String allowedRequest : allowedRequestsForRole) {
			if (allowedRequest.endsWith("*")) {
				requestAllowed = requestPath.startsWith(allowedRequest.substring(0, allowedRequest.length() - 1));
			} else {
				requestAllowed = requestPath.equals(allowedRequest);
			}

			if (requestAllowed) {
				break;
			}
		}

		if (!requestAllowed) {
			logger.info("access denied for user " + (loginJsf != null ? loginJsf.getPersonalData() : "NO_USER")
					+ " and request url " + requestPath);
			((HttpServletResponse) response).sendError(403);
			return;
		}
		chain.doFilter(request, response);
	}

	@Override
	public void destroy() {
	}

	@Override
	public void init(FilterConfig filterConfig) throws ServletException {
	}

}
